home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / comm2 / xbtx.lha / Source / IOSerial.cpp < prev    next >
C/C++ Source or Header  |  1995-12-03  |  13KB  |  713 lines

  1. /*
  2. **    $Id: IOSerial.cpp 1.6 1995/12/03 12:16:23 olsen Exp olsen $
  3. **
  4. **    :ts=4
  5. */
  6.  
  7. /*
  8.  * Amiga changes copyright © 1995 by Olaf Barthel, All Rights Reserved
  9.  *
  10.  * Copyright (c) 1992, 1993 Arno Augustin, Frank Hoering, University of
  11.  * Erlangen-Nuremberg, Germany.
  12.  * All rights reserved.
  13.  *
  14.  * Redistribution and use in source and binary forms, with or without
  15.  * modification, are permitted provided that the following conditions
  16.  * are met:
  17.  * 1. Redistributions of source code must retain the above copyright
  18.  *    notice, this list of conditions and the following disclaimer.
  19.  * 2. Redistributions in binary form must reproduce the above copyright
  20.  *    notice, this list of conditions and the following disclaimer in the
  21.  *    documentation and/or other materials provided with the distribution.
  22.  * 3. All advertising materials mentioning features or use of this software
  23.  *    must display the following acknowledgement:
  24.  *      This product includes software developed by the University of
  25.  *      Erlangen-Nuremberg, Germany.
  26.  * 4. Neither the name of the University nor the names of its contributors
  27.  *    may be used to endorse or promote products derived from this software
  28.  *    without specific prior written permission.
  29.  *
  30.  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
  31.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  32.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
  33.  * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  34.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  35.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  36.  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  37.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  38.  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  39.  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  40.  *
  41.  * This software has not been validated by the ``Bundesamt fuer Zulassungen in
  42.  * der Telekommunikation'' of the ``Deutsche Bundepost Telekom'' and thus
  43.  * must not be used for accessing the BTX-Network of the Telekom in Germany.
  44.  *
  45.  * Diese Software hat keine Zulassung durch das Bundesamt fuer Zulassungen in
  46.  * der Telekommunikation der Deutschen Bundespost Telekom und darf daher nicht
  47.  * am Netz der Deutschen Bundespost Telekom in Deutschland betrieben werden.
  48.  */
  49.  
  50. /****************************************************************************/
  51.  
  52. #include <string.h>
  53. #include <stdio.h>
  54.  
  55. /****************************************************************************/
  56.  
  57. #ifndef _IOSERIAL_HPP
  58. #include "IOSerial.hpp"
  59. #endif
  60.  
  61. #ifndef _CONTROL_H
  62. #include "Control.h"
  63. #endif
  64.  
  65. #ifndef _RAWKEYS_H
  66. #include "RawKeys.h"
  67. #endif
  68.  
  69. /****************************************************************************/
  70.  
  71. #define D(x)
  72.  
  73. /********************  This is CONTROL SET C0 of CEPT ***********************/
  74.  
  75. #define NOBLOCK    0    /* not receiving a block */
  76. #define TEXTBLOCK  1    /* normal text block     */
  77. #define IMAGEBLOCK 2    /* transparent block     */
  78. #define ERROR       0    /* status error          */
  79.  
  80. #define NUL 0x00         /* Null                     (data link) */
  81. #define SOH 0x01         /* start of heading         (data link) */
  82. #define STX 0x02         /* start text                 (data link) */
  83. #define ETX 0x03         /* end text                 (data link) */
  84. #define EOT 0x04         /* end of transmission      (data link) */
  85. #define ENQ 0x05         /* enquiry                  (data link) */
  86. #define ACK 0x06         /* acknowledge              (data link) */
  87. #define ITB 0x07         /* end intermediate block     (data link) */
  88. #define APB 0x08         /* active position back     (control sequence) */
  89. #define APF 0x09         /* active position forward  (control sequence) */
  90. #define APD 0x0a         /* active position down     (control sequence) */
  91. #define APU 0x0b         /* active position up         (control sequence) */
  92. #define CS    0x0c         /* clear screen             (control sequence) */
  93. #define APR 0x0d         /* active position return     (control sequence) */
  94. #define LS1 0x0e         /* locking shift 1          (control sequence) */
  95. #define LS0 0x0f         /* locking shift 0          (control sequence) */
  96. #define DLE 0x10         /* data link escape         (data link) */
  97. #define CON 0x11         /* cursor on                 (control sequence) */
  98. #define RPT 0x12         /* repeat last character     (control sequence) */
  99. #define INI 0x13         /* initiator '*'             (btx special) */
  100. #define COF 0x14         /* cursor off                 (control sequence) */
  101. #define NAK 0x15         /* negative acknowledge     (data link) */
  102. #define SYN 0x16         /*                          (data link) */
  103. #define ETB 0x17         /* end textblock             (data link) */
  104. #define CAN 0x18         /* cancel,clear eol         (control sequence) */
  105. #define SS2 0x19         /* single shift for G2 SET  (control sequence) */
  106. #define DCT 0x1a         /*                          (btx special) */
  107. #define ESC 0x1b         /* escape                     (control sequence) */
  108. #define TER 0x1c         /* terminator '#'             (btx special) */
  109. #define SS3 0x1d         /* single shift for G3 SET  (control sequence) */
  110. #define APH 0x1e         /* active position home     (control sequence) */
  111. #define US    0x1f         /* active position (x,y)     (control sequence) */
  112.  
  113. /****************************************************************************/
  114.  
  115.     // For crc 16 bit calculation using run-time generated table
  116.  
  117. #define calccrc(c)    crc=(UWORD)(crctab[((crc) ^ (c)) & 0xff] ^ ((crc) >> 8))
  118.  
  119. /****************************************************************************/
  120.  
  121. VOID IOSerial::Close(VOID)
  122. {
  123.     if(Raw)
  124.     {
  125.         delete Raw;
  126.  
  127.         Raw = NULL;
  128.     }
  129. }
  130.  
  131. LONG IOSerial::Open(CONST STRPTR Channel,ULONG Unit,ULONG Baud,BOOL RTS_CTS)
  132. {
  133.     LONG Error;
  134.  
  135.     Close();
  136.  
  137.     if(Raw = new IORawSerial)
  138.     {
  139.         if(Error = Raw->Open(Channel,Unit,Baud,RTS_CTS))
  140.         {
  141.             delete Raw;
  142.  
  143.             Raw = NULL;
  144.         }
  145.     }
  146.     else
  147.         Error = -1;
  148.  
  149.     return(Error);
  150. }
  151.  
  152. VOID IOSerial::PutString(CONST STRPTR String,LONG Len)
  153. {
  154.     if(Raw)
  155.     {
  156.         UBYTE *From;
  157.         UBYTE *s,*t;
  158.         char *str;
  159.         UBYTE c;
  160.  
  161.         if(Len < 0)
  162.             Len = strlen(String);
  163.  
  164.         s = (UBYTE *)String;
  165.         t = s + Len;
  166.  
  167.         From = s;
  168.  
  169.         str = NULL;
  170.         c = 0;
  171.  
  172.         while(s < t)
  173.         {
  174.             switch(*s)
  175.             {
  176.                 case 'Ä':
  177.  
  178.                     str = "\310A";
  179.                     break;
  180.  
  181.                 case 'ä':
  182.  
  183.                     str = "\310a";
  184.                     break;
  185.  
  186.                 case 'Ö':
  187.  
  188.                     str = "\310O";
  189.                     break;
  190.  
  191.                 case 'ö':
  192.  
  193.                     str = "\310o";
  194.  
  195.                 case 'Ü':
  196.  
  197.                     str = "\0310U";
  198.                     break;
  199.  
  200.                 case 'ü':
  201.  
  202.                     str = "\310U";
  203.                     break;
  204.  
  205.                 case KEY_CursorUp:
  206.  
  207.                     c = APU;
  208.                     break;
  209.  
  210.                 case KEY_CursorDown:
  211.  
  212.                     c = APD;
  213.                     break;
  214.  
  215.                 case '\b':
  216.                 case 127:
  217.                 case KEY_CursorLeft:
  218.  
  219.                     c = APB;
  220.                     break;
  221.  
  222.                 case KEY_CursorRight:
  223.  
  224.                     c = APF;
  225.                     break;
  226.  
  227.                 case KEY_Help:
  228.  
  229.                     c = APH;
  230.                     break;
  231.  
  232.                 case '*':
  233.  
  234.                     c = INI;
  235.                     break;
  236.  
  237.                 case '#':
  238.                 case '\r':
  239.                 case '\n':
  240.  
  241.                     c = TER;
  242.                     break;
  243.             }
  244.  
  245.             if(str || c)
  246.             {
  247.                 if(From < s)
  248.                     Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  249.  
  250.                 From = s + 1;
  251.  
  252.                 if(str)
  253.                 {
  254.                     Raw->PutString((CONST STRPTR)str,strlen(str));
  255.                     str = NULL;
  256.                 }
  257.                 else
  258.                 {
  259.                     Raw->PutChar(c);
  260.                     c = 0;
  261.                 }
  262.             }
  263.  
  264.             s++;
  265.         }
  266.  
  267.         if(From < s)
  268.             Raw->PutString((CONST STRPTR)From,(LONG)(s - From));
  269.     }
  270. }
  271.  
  272. /* modeminput: this is data link layer (level 2) for getting blocks from
  273.  * btx, crc check is done and characters are send to client
  274.  */
  275.  
  276. int IOSerial::modeminput(LONG Timeout)
  277. {
  278.     LONG c1;
  279.     UBYTE c;
  280.     BOOL eaten;
  281.  
  282.     if(buffered > 0 && buffer_input)
  283.     {
  284.         if(buffered-- == 1)
  285.             buffer_input = FALSE;
  286.  
  287.         return((int)buffer[bufferindex++]);
  288.     }
  289.  
  290.     for(;;)
  291.     {
  292.         c1 = getmodem(Timeout);
  293.  
  294.         if(c1 < 0)
  295.             return(c1);
  296.         else
  297.             c = (UBYTE)c1;
  298.  
  299.         switch( block )
  300.         {
  301.             case IMAGEBLOCK:
  302.  
  303.                 eaten = FALSE;
  304.  
  305.                 switch(c)
  306.                 {
  307.                     case DLE:
  308.  
  309.                         if(got_dle)
  310.                             got_dle = FALSE;
  311.                         else
  312.                         {
  313.                             got_dle = TRUE;
  314.  
  315.                             eaten = TRUE;
  316.                         }
  317.  
  318.                         break;
  319.  
  320.                     case ENQ:
  321.  
  322.                         if(got_dle)
  323.                         {
  324.                             buffered = bufferlen = 0;
  325.                             buffer_input = FALSE;
  326.                             ack01 = '0';
  327.                             block = NOBLOCK;
  328.                             got_itb_bcc = FALSE;
  329.  
  330.                             putmodem(DLE);
  331.                             putmodem(ack01);
  332.  
  333.                             eaten = TRUE;
  334.                             got_dle = FALSE;
  335.                         }
  336.  
  337.                         break;
  338.  
  339.                     case EOT:
  340.  
  341.                         if(status == ERROR || got_dle)
  342.                         {
  343.                             buffered = bufferlen = 0;
  344.                             buffer_input = FALSE;
  345.                             ack01 = '0';
  346.                             block = NOBLOCK;
  347.                             got_itb_bcc = FALSE;
  348.  
  349.                             eaten = TRUE;
  350.                             got_dle = FALSE;
  351.                         }
  352.  
  353.                         break;
  354.  
  355.                     case ITB:
  356.                     case ETB:
  357.                     case ETX:
  358.  
  359.                         if(got_dle)
  360.                         {
  361.                             got_dle = FALSE;
  362.  
  363.                             calccrc(c);
  364.  
  365.                             eaten = TRUE;
  366.  
  367.                             if(getcheck(Timeout) || status == ERROR)
  368.                             {
  369.                                 buffered = bufferlen = 0;
  370.                                 buffer_input = FALSE;
  371.                                 crc = 0;
  372.                                 putmodem(NAK);
  373.                                 status = ERROR;
  374.  
  375.                                 got_itb_bcc = FALSE;
  376.                                 got_dle = FALSE;
  377.  
  378.                                 break;
  379.                             }
  380.  
  381.                             status = c;
  382.  
  383.                             block = NOBLOCK;
  384.  
  385.                             if(c == ITB)
  386.                             {
  387.                                 putmodem(ACK);
  388.                                 got_itb_bcc = TRUE;
  389.                             }
  390.                             else
  391.                             {
  392.                                 ack01 ^= 1;
  393.                                 putmodem(DLE);
  394.                                 putmodem(ack01);
  395.                                 got_itb_bcc = FALSE;
  396.                             }
  397.  
  398.                             if(bufferlen > 0)
  399.                             {
  400.                                 buffer_input = TRUE;
  401.                                 buffered = bufferlen - 1;
  402.                                 bufferindex = 1;
  403.  
  404.                                 bufferlen = 0;
  405.  
  406.                                 return((int)buffer[0]);
  407.                             }
  408.                         }
  409.  
  410.                         break;
  411.                 }
  412.  
  413.                 if(!eaten)
  414.                 {
  415.                     calccrc(c);
  416.  
  417.                     if(bufferlen < BLOCK_BUFFER_SIZE-1)
  418.                     {
  419.                         buffer[bufferlen++] = c;
  420.                         got_itb_bcc = FALSE;
  421.                     }
  422.                     else
  423.                         D(printf("Blockbuffer overflow !\n"));
  424.                 }
  425.  
  426.                 break;
  427.  
  428.             case TEXTBLOCK:
  429.  
  430.                 calccrc(c);
  431.  
  432.                 switch(c)
  433.                 {
  434.                     case DLE:
  435.                     case NAK:
  436.                     case ACK:
  437.                     case SOH:
  438.  
  439.                         D(printf("Bad char:%x\n",c1));
  440.                         got_itb_bcc = FALSE;
  441.                         break;
  442.  
  443.                     case STX:
  444.  
  445.                         if(status == ERROR || status == ETB)
  446.                         {
  447.                             crc = 0;
  448.                             bufferlen = 0;
  449.                             status = EOT;
  450.                             got_itb_bcc = FALSE;
  451.                         }
  452.  
  453.                         break;
  454.  
  455.                     case EOT:
  456.  
  457.                         ack01 = '0';
  458.                         block = NOBLOCK;
  459.                         got_itb_bcc = FALSE;
  460.                         break;
  461.  
  462.                     case ITB:
  463.                     case ETB:
  464.                     case ETX:
  465.  
  466.                         if(getcheck(Timeout) || status == ERROR)
  467.                         {
  468.                             buffer_input = FALSE;
  469.                             buffered = bufferlen = 0;
  470.                             crc = 0;
  471.                             putmodem(NAK);
  472.                             status = ERROR;
  473.                             got_itb_bcc = FALSE;
  474.  
  475.                             break;
  476.                         }
  477.  
  478.                         status = c;
  479.  
  480.                         if(c == ITB)
  481.                         {
  482.                             putmodem(ACK);
  483.                             got_itb_bcc = TRUE;
  484.                         }
  485.                         else
  486.                         {
  487.                             ack01 ^= 1;
  488.                             putmodem(DLE);
  489.                             putmodem(ack01);
  490.  
  491.                             if(c == ETX)
  492.                                 block = NOBLOCK;  /* end of textblock */
  493.  
  494.                             got_itb_bcc = FALSE;
  495.                         }
  496.  
  497.                         if(bufferlen > 0)
  498.                         {
  499.                             buffer_input = TRUE;
  500.                             buffered = bufferlen - 1;
  501.                             bufferindex = 1;
  502.  
  503.                             bufferlen = 0;
  504.  
  505.                             return((int)buffer[0]);
  506.                         }
  507.  
  508.                         break;
  509.  
  510.                     case ENQ:
  511.  
  512.                          switch( status )
  513.                         {
  514.                             case ERROR:
  515.                             case EOT:
  516.  
  517.                                 putmodem(NAK);
  518.                                 break;
  519.  
  520.                             case ITB:
  521.  
  522.                                 putmodem(ACK);
  523.                                 putmodem(NAK);
  524.                                 break;
  525.  
  526.                             case ETX:
  527.                             case ETB:
  528.  
  529.                                 putmodem(DLE);
  530.                                 putmodem(ack01);
  531.                                 putmodem(NAK);
  532.                                 break;
  533.                         }
  534.  
  535.                         got_itb_bcc = FALSE;
  536.  
  537.                         break;
  538.  
  539.                     default:
  540.  
  541.                         if(bufferlen < BLOCK_BUFFER_SIZE-1)
  542.                         {
  543.                             buffer[bufferlen++] = c;
  544.                             got_itb_bcc = FALSE;
  545.                         }
  546.                         else
  547.                             D(printf("Blockbuffer overflow !\n"));
  548.  
  549.                         break;
  550.                 }
  551.  
  552.                 break;
  553.  
  554.             default:      /* NOBLOCK */
  555.  
  556.                 status = EOT;
  557.  
  558.                 if(tfi)
  559.                 {
  560.                     if(tfi == SOH)
  561.                         tfi = ENQ;
  562.                     else
  563.                     {
  564.                         if(c == ENQ)
  565.                         {
  566.                             D(printf("send TFI\n"));
  567.                             send_TFI();
  568.                         }
  569.  
  570.                         tfi = 0;
  571.                     }
  572.                 }
  573.  
  574.                 switch(c)
  575.                 {
  576.                     case DLE:
  577.  
  578.                         got_dle = TRUE;
  579.                         break;
  580.  
  581.                     case ENQ:
  582.  
  583.                         if(got_dle)
  584.                         {
  585.                             putmodem(DLE);
  586.                             putmodem('0');
  587.                         }
  588.  
  589.                         got_dle = FALSE;
  590.                         break;
  591.  
  592.                     case EOT:
  593.  
  594.                         ack01 = '0';
  595.                         got_dle = FALSE;
  596.                         break;
  597.  
  598.                     case SOH:
  599.  
  600.                         tfi = SOH;
  601.                         crc = 0;
  602.                         block = TEXTBLOCK;
  603.                         bufferlen = 0;
  604.                         got_dle = FALSE;
  605.                         break;
  606.  
  607.                     case STX:
  608.  
  609.                         if(got_dle)
  610.                             block = IMAGEBLOCK;
  611.                         else
  612.                             block = TEXTBLOCK;
  613.  
  614.                         crc = 0;
  615.                         bufferlen = 0;
  616.  
  617.                         if(got_dle && got_itb_bcc)
  618.                         {
  619.                             got_itb_bcc = FALSE;
  620.  
  621.                             calccrc(DLE);
  622.                             calccrc(STX);
  623.                         }
  624.  
  625.                         got_dle = FALSE;
  626.                         break;
  627.  
  628.                     default:
  629.  
  630.                         got_dle = FALSE;
  631.                         return((int)c);
  632.                 }
  633.  
  634.                 break;
  635.         }
  636.     }
  637. }
  638.  
  639. void IOSerial::send_TFI()
  640. {
  641.    putmodem(SOH);
  642.    putmodem('@');  /* @ = intermediate blocksize */
  643.    putmodem('5');  /* 5 = max. 256 bytes         */
  644.    putmodem(ETX);
  645. }
  646.  
  647. /* get 2 bytes from modem and calccrc, return value is crc (should be 0 if
  648.  * no crc error), during check handle socket inputs
  649.  */
  650. UWORD IOSerial::getcheck(LONG Timeout)
  651. {
  652.     LONG c;
  653.     int i;
  654.  
  655.     for(i = 0 ; i < 2 ; )
  656.     {
  657.         c = getmodem(Timeout);
  658.  
  659.         if(c >= 0)
  660.         {
  661.             calccrc((unsigned int)c);
  662.             i++;
  663.         }
  664.     }
  665.  
  666.     if(crc)
  667.         D(printf("CRC error %x\n",(int)crc));
  668.  
  669.     return(crc);
  670. }
  671.  
  672. /******************************************************************************/
  673.  
  674. IOSerial::IOSerial()
  675. {
  676.     UWORD crc;
  677.     int i,j;
  678.  
  679.     Raw                = NULL;
  680.  
  681.     block            = NOBLOCK;
  682.     bufferlen        = 0;
  683.     tfi                = 0;
  684.     ack01            = '0';
  685.     status            = EOT;
  686.     crc                = 0;
  687.     buffered        = 0;
  688.     buffer_input    = FALSE;
  689.  
  690.     got_dle            = FALSE;
  691.     got_itb_bcc        = FALSE;
  692.  
  693.     for(i = 0 ; i < 256 ; i++)
  694.     {
  695.         crc = (UWORD)i;
  696.  
  697.         for(j = 0 ; j < 8 ; j++)
  698.         {
  699.             if(crc & 1)
  700.                 crc = (UWORD)((crc >> 1) ^ 0xa001);
  701.             else
  702.                 crc >>= 1;
  703.         }
  704.  
  705.         crctab[i] = crc;
  706.     }
  707. }
  708.  
  709. IOSerial::~IOSerial()
  710. {
  711.     Close();
  712. }
  713.